#include "Shader.h"
#include "Vector3.h"
#include "RayTracer.h"
#include "trax.hpp"

namespace AtomTrace
{  
    const Color shade(const Ray & iRay, const HitRecord & hRec, const Scene & scene)
    {
        Vector3 V = iRay._dir * -1.0f;
        Color res(0.0f, 0.0f, 0.0f);
        //res.Set(0.0f, 0.0f, 0.0f);
        int diffAddr = scene.startMatAddr + hRec.matID * 25;
        //const Color & mat = scene.materials[hRec.matID];
        Color diffuse;
        diffuse.LoadFromGM(diffAddr+4);
        //const Vector3 & N = hRec.N;
        Vector3 N = hRec.GetTriangleNormal();

        // ambient light
        res += diffuse*scene.lambient*scene.ka;
        int lightSize = 3;
        for(int lightID = 0; lightID<scene.numLights; lightID++)
        {
            PointLight pl;
            pl.LoadFromGM(scene.startLightAddr + lightID * lightSize);
            Vector3 L = pl.GetDirection(hRec.P);
            float nDotL = N.Dot(L);
            float nDotV = N.Dot(V);

            // <Shadow check> --------------------------------
            float dst = (pl.pos - hRec.P).Length();
            Ray shadow = RayTracer::CastRay(hRec.P, L);
            //Ray shadow = RayTracer::CastRay(hRec.P, pl.pos-hRec.P);

            HitRecord shadowHit;
            shadowHit.Init();
            //shadowHit.t = dst;
            //bool isHit = RayTracer::TraceRay(shadow, scene, shadowHit);
            bool isHit = RayTracer::TraceBVH(shadow, shadowHit);
            if(shadowHit.t < dst) continue;
            // ----------------------------</Shadow check>*/

            const Color & I = pl.intensity;
            
            float cosT;// = max(nDotL, 0.0f);
            //cosT = (N.Dot(L));
            //if(cosT < 0.0f) cosT = -cosT;
            if(nDotL * nDotV < 0.0f) cosT = 0.0f;
            else cosT = max(nDotL, -nDotL);
            res += diffuse*I*cosT * scene.kd; // only diffuse lighting
        }

        return res;
    }
} // namespace AtomTrace
